import { Threebox, THREE } from 'threebox-plugin'
import axios from 'axios'
import Event from '@/libs/event'
import util from '@/libs/util'

const animateCor = 0.00015 // 正则向北，负则向南

class ThreeBox extends Event {
  constructor (id) {
    super()
    this.id = id
    this.type = 'custom'
    this.renderingMode = '3d'
    
    this.bearingAngle = 0
    this.isAnimate = false
  }

  onAdd (map, gl) {
    this.map = map
    this.tb = window.tb = new Threebox( map, gl,
      {
        defaultLights: true,
        enableSelectingObjects: true
      }
    )
  }

  render (gl, matrix) {
    this.tb.update()
    this.map.triggerRepaint()
  }

  highLightFloor (e) {
    // 显示房间信息
    let newObj = null
    if (e.detail) {
      newObj = e.detail.clone()
    } else {
      newObj = e.clone()
    }
    newObj.name = newObj.name + '-highLight'
    newObj.raycasted = false
    // 检查场景中是否已经有高亮
    const isHighLight = this.tb.scene.getObjectByName(newObj.name)
    if (isHighLight) {
      return
    }
    newObj.traverse((e2) => {
      if (e2.isMesh) {
        e2.material = new THREE.MeshBasicMaterial({
          color: 0xffff00,
          opacity: 0.1,
          transparent: true
        })
      }
    })
    this.tb.add(newObj)
  }

  unLightFloor (e) {
    const model = e.detail
    const hilightName = model.name + '-highLight'
    const hilightObject = this.tb.scene.getObjectByName(hilightName)
    if (hilightObject) {
      this.tb.remove(hilightObject)
    }
  }

  floorPopAnimate (model, dis, bearingAngle) {
    const startTime = new Date().getTime()
    const duration = 1000
    let transformModel = model.model || model
    const { x, y, z } = transformModel.position

    const animate = () => {
      const timeDiff = new Date().getTime() - startTime
      if (timeDiff > duration) {
        this.isAnimate = false
      } else {
        this.isAnimate = true
        const newX = this.easeOutQuad(timeDiff, x, -dis * Math.sin(bearingAngle), duration)
        const newY = this.easeOutQuad(timeDiff, y, -dis * Math.cos(bearingAngle), duration)
        transformModel.position.x = newX
        transformModel.position.y = newY
        requestAnimationFrame(animate)
      }
    }
    animate()
  }

  adjustFreeCamera (model) {
    // 计算3dmax坐标在地图上偏移后的经纬度
    const [x, y, z] = [...model.coordinates]
    const pos = [
      x + 2.5 * animateCor * Math.sin(util.deg2arc(-this.bearingAngle)),
      y - 2.5 * animateCor * Math.cos(util.deg2arc(-this.bearingAngle))
    ]
    const altitue = model.coordinates[2]
    const pos3D = util.max2lnglat(
      { x: model.center.x, y: model.center.y },
      pos
    )

    const camera = this.map.getFreeCameraOptions()
    // 起始点与终点POS，墨卡托坐标系的xyz
    const startPos = Object.values(this.map.getFreeCameraOptions().position)
    const endPos = Object.values(mapboxgl.MercatorCoordinate.fromLngLat(pos3D, altitue + 30))
    // 起始点与终点的目标点，经纬度
    const startLookat = [...Object.values(this.map.getCenter())]

    const projectedY = model.center.y -
      altitue * Math.tan((this.map.getPitch() * Math.PI) / 180)

    const endLookat = [...Object.values(util.max2lnglat(
      { x: model.center.x, y: projectedY },
      [model.coordinates[0], model.coordinates[1]]
    ))]

    const startPitch = this.map.getPitch()
    const startBearing = this.map.getBearing()
    // 相机的坐标、中心点经纬度、倾斜角的差值
    const posDiff = endPos.map((ele, index) => {
      return ele - startPos[index]
    })
    const centerDiff = endLookat.map((ele, index) => {
      return ele - startLookat[index]
    })
    const pitchDiff = this.pitch - startPitch
    const bearingDiff = this.bearingAngle - startBearing

    const duration = 1000
    const startTime = new Date().getTime()
    const cameraAnimate = () => {
      const timeDiff = new Date().getTime() - startTime
      if (timeDiff >= duration) {
      } else {
        camera.position = startPos.map((ele, index) => {
          return this.easeOutQuad(timeDiff, ele, posDiff[index], duration)
        })
        const lookat = startLookat.map((ele, index) => {
          return this.easeOutQuad(timeDiff, ele, centerDiff[index], duration)
        })
        const lookPitch = this.easeOutQuad(timeDiff, startPitch, pitchDiff, duration)
        const lookBearing = this.easeOutQuad(timeDiff, startBearing, bearingDiff, duration)
        camera.lookAtPoint(lookat)
        camera.setPitchBearing(lookPitch, lookBearing)
        this.map.setFreeCameraOptions(camera)
        requestAnimationFrame(cameraAnimate)
      }
    }
    cameraAnimate()
  }

  easeOutQuad (currentTime, startValue, changeValue, duration) {
    currentTime /= duration
    return -changeValue * currentTime * (currentTime - 2) + startValue
  }
}

export default ThreeBox
